﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NUnit.Framework;
using OneOfAKind.Toolbox.WebTools;
using System.Globalization;
using Agility.TestProject.AppDriver;
using Agility.Wcf.ClientProxy;
using System.Diagnostics.CodeAnalysis;
using Agility.Wcf.ClientProxy.RequirementsManagementServiceClient;

namespace Agility.Testing.WcfProxy
{
    [TestFixture]
    public class AgilityClientProxyProxyTests
    {
        Agility.Wcf.ClientProxy.AgilityClientProxy target;
        string agilityUrl = "http://localhost:52878/";
        string username;
        string password = "Test##100";
        AppDriverBase appDriverBase;

        #region optional Setup and Teardown methods

        [TestFixtureSetUp]
        public void SetupFixture()
        {
            appDriverBase = new AppDriverBase();
            appDriverBase.Initialize();
            username = appDriverBase.UserName;
        }

        [TestFixtureTearDown]
        public void TeardownFixture()
        {
            appDriverBase.Cleanup();
        }

        [SetUp]
        public void SetupTest()
        {
            this.target = AgilityClientProxy.GetInstance(new Uri(agilityUrl));
        }

        [TearDown]
        public void TeardownTest()
        {
            this.target.Dispose();
            this.target = null;
        }

        #endregion

        #region UnitTests

        [Test]
        [Category("UnitTest")]
        [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic")]
        public void TestConstructorForHttp()
        {
            // Act
            AgilityClientProxy target2 = AgilityClientProxy.GetInstance(new Uri(this.agilityUrl));

            // Assert
            Assert.IsNotNull(this.target);
            Assert.That(this.target.AgilityUrl.AbsoluteUri, Is.EqualTo(agilityUrl));
            Assert.That(this.target, Is.SameAs(target2));
        }

        [Test]
        [Category("UnitTest")]
        [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic")]
        public void TestConstructorForHttps()
        {
            // Arrange
            this.target.Dispose();
            string url = "https://localhost:52878/";

            // Act
            this.target = AgilityClientProxy.GetInstance(new Uri(url));

            // Assert
            Assert.IsNotNull(this.target);
            Assert.That(this.target.AgilityUrl.AbsoluteUri, Is.EqualTo(url));
        }

        #endregion

        #region ComponentTests
        
        [Test]
        [Category("ComponentTest")]
        [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic")]
        public void TestLogOn()
        {
            // Arrange
            bool actual = false;
            bool eventFired = false;
            target.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler((o, pea) =>
                {
                    if (pea.PropertyName == "IsLoggedOn")
                    {
                        eventFired = true;
                    }
                });

            // Act
            this.target.LogOn(this.username, this.password);
            actual = this.target.IsLoggedOn;

            // Assert
            Assert.That(actual, Is.True);
            Assert.That(eventFired, Is.True);
        }

        [Test]
        [Category("ComponentTest")]
        [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic")]
        public void TestLogOff()
        {
            // Arrange
            bool actual = false;
            bool eventFired = false;
            this.target.LogOn(this.username, this.password);
            this.target.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler((o, pea) =>
                {
                    if (pea.PropertyName == "IsLoggedOn")
                    {
                        eventFired = true;
                    }
                });
            // Act
            this.target.LogOff();
            actual = this.target.IsLoggedOn;

            // Assert
            Assert.That(actual, Is.False);
            Assert.That(eventFired, Is.True);
        }


        [Test]
        [Category("ComponentTest")]
        [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic")]
        public void TestPersistentLogOn()
        {
            // Arrange
            string actual = string.Empty;
            StringBuilder userConfigPath = new StringBuilder(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData));
            userConfigPath.Append("\\NUnit.org\\");
            System.IO.DirectoryInfo folder = new System.IO.DirectoryInfo(userConfigPath.ToString());
            System.IO.DirectoryInfo[] subfolders = folder.GetDirectories("test*");
            userConfigPath.Append(subfolders[0]).Append("\\");
            folder = new System.IO.DirectoryInfo(userConfigPath.ToString());
            subfolders = folder.GetDirectories();
            subfolders.OrderBy(sf => sf.CreationTime);
            userConfigPath.Append(subfolders.Last()).Append("\\user.config");
            System.Xml.XmlDocument settingsDoc = new System.Xml.XmlDocument();
            target.KeepMeLoggedOn = true;

            // Act
            target.LogOn(this.username, this.password);
            Assert.That(target.IsLoggedOn, Is.True);
            target.Dispose();

            settingsDoc.Load(userConfigPath.ToString());
            actual = settingsDoc.DocumentElement.SelectSingleNode("descendant::userSettings/Agility.Wcf.ClientProxy.Properties.Settings/setting[@name=\"Cookie\"]").FirstChild.InnerText;
            
            // Assert
            Assert.That(actual, Is.Not.Null);
        }

        [Test]
        [Category("ComponentTest")]
        [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic")]
        public void TestGetMyEpics()
        {
            // Arrange
            appDriverBase.CreateEpicsForMyIdeas();
            List<Agility.Web.Models.DomainModel.Epic> expected = appDriverBase.TestEpics.Where(e => e.RequestedBy == appDriverBase.UserName).ToList();
            expected = expected.OrderBy(e => e.Id).ToList();
            List<Epic> actual = null;

            // Act
            target.LogOn(this.username, this.password);
            actual = target.GetMyIdeas();
            target.LogOff();
            actual = actual.OrderBy(e => e.Id).ToList();

            // Assert
            Assert.That(actual.Count, Is.EqualTo(expected.Count));
            for (int i = 0; i < actual.Count; i++)
            {
                Assert.That(actual[i].Id, Is.EqualTo(expected[i].Id));
            }
        }


        [Test]
        [Category("ComponentTest")]
        [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic")]
        public void TestSubmitChangesUpdate()
        {
            // Arrange
            string expected = "My updated Title";
            string actual = string.Empty;
            appDriverBase.CreateEpicsForMyIdeas();
            target.LogOn(this.username, this.password);
            Epic originalIdea = target.GetMyIdeas().Where(e => e.RequestedBy == this.username).First();
            Epic updated = new Epic()
            {
                Id = originalIdea.Id,
                CreationDate = originalIdea.CreationDate,
                Description = originalIdea.Description,
                RequestedBy = originalIdea.RequestedBy,
                Title = expected
            };
            // TODO: Submit all epics, not just the updated
            List<Epic> epics = new List<Epic>();
            epics.Add(updated);

            // Act
            target.SubmitChanges(epics);
            actual = target.GetMyIdeas().SingleOrDefault(i => i.Id == updated.Id).Title;
            target.LogOff();

            // Assert
            Assert.That(actual, Is.EqualTo(expected));
        }


        [Test]
        [Category("ComponentTest")]
        [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic")]
        public void TestSubmitChangesInsert()
        {
            // Arrange
            Epic actual = null;
            appDriverBase.CreateEpicsForMyIdeas();
            target.LogOn(this.username, this.password);
            target.GetMyIdeas();
            Epic expected = new Epic();
            expected.CreationDate = DateTime.Today;
            expected.Description = "The description of my new idea";
            expected.RequestedBy = this.username;
            expected.Title = "My new Idea";
            // TODO: Submit all epics, not just the inserted
            List<Epic> epics = new List<Epic>();
            epics.Add(expected);

            // Act
            target.SubmitChanges(epics);
            List<Epic> storedEpics = target.GetMyIdeas();
            target.LogOff();
            actual = storedEpics.SingleOrDefault(a => a.Id == expected.Id);

            // Assert
            Assert.That(actual, Is.Not.Null);
            Assert.That(actual.CreationDate, Is.EqualTo(expected.CreationDate));
            Assert.That(actual.Description, Is.EqualTo(expected.Description));
            Assert.That(actual.Id, Is.EqualTo(expected.Id));
            Assert.That(actual.RequestedBy, Is.EqualTo(expected.RequestedBy));
            Assert.That(actual.Title, Is.EqualTo(expected.Title));
        }
        
        
        #endregion
    }
}
